package lpca.utils.MazeGenerator 
{
	import adobe.utils.CustomActions;
	import lpca.model.*;
	import lpca.utils.*;
	/**
	 * ...
	 * @author Figishe
	 */
	public class MazeGeneratorSet 
	{
		public static const ELEMENT_SIZE: int = 5; // длина стороны элемента
		
		private var eqClass: Vector.<Vector.<Vector.<Vector.<Vector.<Matrix>>>>>; // ок? 
		private var heap: Vector.<Matrix>;
		
		
		
		public function MazeGeneratorSet() 
		{
			// инициализация вложенных векторов
			eqClass = new Vector.<Vector.<Vector.<Vector.<Vector.<Matrix>>>>>(ELEMENT_SIZE - 1); // 0,1,2,3
			for (var side1: int = 0; side1 < (ELEMENT_SIZE - 1); side1++)
			{
				eqClass[side1] = new Vector.<Vector.<Vector.<Vector.<Matrix>>>>(ELEMENT_SIZE - 1);
				for (var side2: int = 0; side2 < (ELEMENT_SIZE - 1); side2++)
				{
					eqClass[side1][side2] = new Vector.<Vector.<Vector.<Matrix>>>(ELEMENT_SIZE - 1);
					for (var side3: int = 0; side3 < (ELEMENT_SIZE - 1); side3++)
					{
						eqClass[side1][side2][side3] = new Vector.<Vector.<Matrix>>(ELEMENT_SIZE - 1);
						for (var side4: int = 0; side4 < (ELEMENT_SIZE - 1); side4++)
						{
							eqClass[side1][side2][side3][side4] = new Vector.<Matrix>(); // расширяемый класс эквивалентности
						}
					}
				}
			}
			initHeap();
			trace('Паззлы отсортированы, всего:', sortHeap());
		}
		
		public function getClassRndPuzzle(side1: int, side2: int, side3: int, side4: int): Matrix
		{
			// случайный элемент класса
			//trace('getClassRndPuzzle(', side1, side2, side3, side4, '): class length = ', eqClass[side1][side2][side3][side4].length);
			if (eqClass[side1][side2][side3][side4].length != 0)
				return eqClass[side1][side2][side3][side4][System.randRange(0, eqClass[side1][side2][side3][side4].length - 1)]
			else 
			{
				trace('getClassRndPuzzle(', side1, side2, side3, side4, ') - пустой класс.');
				return new Matrix(ELEMENT_SIZE, ELEMENT_SIZE, new Vector.<int>(ELEMENT_SIZE * ELEMENT_SIZE));
			}
		}
		
		private function sortHeap(): int // сортировка кучи по eqClass 
		{
			var total: int = 0;
			for (var side1: int = 0; side1 < (ELEMENT_SIZE - 1); side1++)
			{
				for (var side2: int = 0; side2 < (ELEMENT_SIZE - 1); side2++)
				{
					for (var side3: int = 0; side3 < (ELEMENT_SIZE - 1); side3++)
					{
						for (var side4: int = 0; side4 < (ELEMENT_SIZE - 1); side4++)
						{
							for (var counter: int = 0; counter < heap.length; counter++)
							{
								//trace('Sides to be checked: ', ELEMENT_SIZE - 1 ,side1 + 1, side2 + 1, side3 + 1, side4 + 1);
								// TODO: отдельно для крайних
								if (((heap[counter].val(side1, 0) == 0) || (side1 == 0))
								&& ((heap[counter].val(ELEMENT_SIZE - 1, side2) == 0) || (side2 == 0))
								&& ((heap[counter].val(side3, ELEMENT_SIZE - 1) == 0) || (side3 == 0)) 
								&& ((heap[counter].val(0, side4) == 0) || (side4 == 0)))
								{
									eqClass[side1][side2][side3][side4].push(heap[counter]); // если соотв. значения - нули, помещаем в класс эквивалентности
									total++;
								}
							}
						}
					}
				}
			}
			return total;
		}
		
		private function pushCombinations(matrix: Matrix): void
		{
			var mat90: Matrix = matrix.rotate90(); 
			var mat180: Matrix = mat90.rotate90(); 
			var mat270: Matrix = matrix.rotate270(); 
			
			heap.push(matrix);
			
			heap.push(mat90);
			heap.push(mat180);
			heap.push(mat270);
			
			heap.push(mat90.mirrorX());
			heap.push(mat180.mirrorX());
			heap.push(mat270.mirrorX());
			
			//heap.push(mat90.mirrorY());
			heap.push(mat180.mirrorY());
			//heap.push(mat270.mirrorY());
		}
		
		private function initHeap(): void // создание кучи паззлов
		{
			heap = new Vector.<Matrix>(0, false); // создание расширяемой кучи
			var puzzle: Matrix;
			
			puzzle = new Matrix(ELEMENT_SIZE, ELEMENT_SIZE, new <int>[
			1, 0, 1, 1, 1,
			0, 0, 0, 0, 0,
			0, 0, 0, 0, 1,
			0, 0, 0, 0, 1,
			1, 0, 1, 1, 1]);
			// 1111 1112 1113
			pushCombinations(puzzle);
			
			puzzle = new Matrix(ELEMENT_SIZE, ELEMENT_SIZE, new <int>[
			1, 0, 1, 1, 1,
			1, 0, 0, 0, 0,
			0, 0, 1, 1, 1,
			0, 0, 0, 0, 1,
			1, 1, 0, 1, 1]);
			// 1122 1123
			pushCombinations(puzzle);
			
			puzzle = new Matrix(ELEMENT_SIZE, ELEMENT_SIZE, new <int>[
			1, 1, 1, 1, 1,
			1, 0, 0, 0, 0,
			1, 0, 0, 0, 0,
			1, 0, 0, 0, 0,
			1, 0, 0, 0, 0]);
			pushCombinations(puzzle);
			
			puzzle = new Matrix(ELEMENT_SIZE, ELEMENT_SIZE, new <int>[
			1, 0, 1, 1, 1,
			1, 0, 0, 0, 0,
			1, 1, 1, 0, 1,
			0, 0, 0, 0, 1,
			1, 1, 1, 0, 1]);
			// 1133
			pushCombinations(puzzle);
			
			puzzle = new Matrix(ELEMENT_SIZE, ELEMENT_SIZE, new <int>[
			1, 0, 1, 1, 1,
			1, 0, 0, 0, 1,
			0, 0, 1, 0, 0,
			0, 0, 0, 0, 1,
			1, 0, 1, 1, 1]);
			// 1212 1213
			pushCombinations(puzzle);
			
			puzzle = new Matrix(ELEMENT_SIZE, ELEMENT_SIZE, new <int>[
			1, 0, 1, 1, 1,
			1, 0, 0, 1, 1,
			0, 0, 0, 0, 0,
			0, 1, 0, 1, 1,
			1, 1, 0, 1, 1]);
			// 1222 1223
			pushCombinations(puzzle);
			
			puzzle = new Matrix(ELEMENT_SIZE, ELEMENT_SIZE, new <int>[
			1, 0, 1, 1, 1,
			1, 0, 1, 0, 1,
			0, 0, 1, 0, 0,
			0, 0, 0, 0, 1,
			1, 1, 1, 0, 1]);
			// 1232 1233
			pushCombinations(puzzle);
			
			puzzle = new Matrix(ELEMENT_SIZE, ELEMENT_SIZE, new <int>[
			1, 0, 1, 1, 1,
			1, 0, 1, 1, 1,
			1, 0, 1, 1, 1,
			0, 0, 0, 0, 0,
			1, 0, 0, 1, 1]);
			//1313 1323
			pushCombinations(puzzle);
			
			puzzle = new Matrix(ELEMENT_SIZE, ELEMENT_SIZE, new <int>[
			1, 0, 1, 1, 1,
			1, 0, 0, 0, 1,
			1, 0, 1, 0, 1,
			0, 0, 0, 0, 0,
			1, 1, 1, 0, 1]);
			// 1333
			pushCombinations(puzzle);
			
			puzzle = new Matrix(ELEMENT_SIZE, ELEMENT_SIZE, new <int>[
			1, 1, 0, 1, 1,
			1, 1, 0, 1, 1,
			0, 0, 0, 0, 0,
			1, 1, 0, 1, 1,
			1, 1, 0, 1, 1]);
			// 2222
			pushCombinations(puzzle);
			
			puzzle = new Matrix(ELEMENT_SIZE, ELEMENT_SIZE, new <int>[
			1, 1, 0, 1, 1,
			1, 1, 0, 1, 1,
			1, 1, 0, 0, 0,
			0, 0, 0, 0, 1,
			1, 1, 0, 1, 1]);
			// 2223
			pushCombinations(puzzle);
			
			puzzle = new Matrix(ELEMENT_SIZE, ELEMENT_SIZE, new <int>[
			1, 0, 1, 1, 1,
			1, 0, 0, 0, 1,
			1, 0, 1, 0, 1,
			0, 0, 1, 0, 0,
			1, 1, 1, 0, 1]);
			// 1333
			pushCombinations(puzzle);
			
			puzzle = new Matrix(ELEMENT_SIZE, ELEMENT_SIZE, new <int>[
			1, 1, 1, 0, 1,
			1, 0, 1, 0, 1,
			1, 0, 1, 0, 0,
			0, 0, 0, 0, 0,
			1, 1, 0, 0, 1]);
			// 3323 3333 3223 3233
			pushCombinations(puzzle);
			
			puzzle = new Matrix(ELEMENT_SIZE, ELEMENT_SIZE, new <int>[
			1, 1, 0, 1, 1,
			1, 0, 0, 0, 1,
			1, 0, 0, 0, 0,
			0, 0, 0, 0, 0,
			1, 1, 1, 0, 1]);
			// 2233 2333
			pushCombinations(puzzle);
			
			puzzle = new Matrix(ELEMENT_SIZE, ELEMENT_SIZE, new <int>[
			1, 0, 1, 1, 1,
			1, 0, 0, 1, 0,
			0, 0, 0, 0, 0,
			1, 1, 0, 0, 1,
			1, 1, 0, 1, 1]);
			pushCombinations(puzzle);
			
			puzzle = new Matrix(ELEMENT_SIZE, ELEMENT_SIZE, new <int>[
			1, 1, 1, 0, 1,
			1, 1, 1, 0, 0,
			0, 0, 1, 0, 1,
			1, 0, 0, 0, 1,
			1, 1, 1, 0, 1]);
			pushCombinations(puzzle);
			
			puzzle = new Matrix(ELEMENT_SIZE, ELEMENT_SIZE, new <int>[
			1, 1, 1, 0, 1,
			1, 0, 0, 0, 0,
			1, 1, 1, 0, 1,
			1, 1, 1, 0, 1,
			1, 1, 1, 0, 1]);
			pushCombinations(puzzle);
			
			puzzle = new Matrix(ELEMENT_SIZE, ELEMENT_SIZE, new <int>[
			1, 1, 1, 0, 1,
			1, 1, 1, 0, 1,
			1, 1, 1, 0, 0,
			0, 0, 0, 0, 1,
			1, 0, 1, 1, 1]);
			// 3213
			pushCombinations(puzzle);
			
			puzzle = new Matrix(ELEMENT_SIZE, ELEMENT_SIZE, new <int>[
			1, 0, 1, 1, 1,
			0, 0, 0, 1, 1,
			1, 1, 0, 1, 1,
			1, 1, 0, 0, 0,
			1, 1, 0, 1, 1]);
			// 1321
			pushCombinations(puzzle);
			
			puzzle = new Matrix(ELEMENT_SIZE, ELEMENT_SIZE, new <int>[
			1, 1, 1, 0, 1,
			1, 0, 1, 0, 0,
			1, 0, 1, 0, 1,
			0, 0, 0, 0, 1,
			1, 0, 1, 1, 1]);
			// 3113
			pushCombinations(puzzle);
			
			puzzle = new Matrix(ELEMENT_SIZE, ELEMENT_SIZE, new <int>[
			1, 1, 0, 1, 1,
			1, 0, 0, 0, 1,
			1, 0, 0, 0, 0,
			0, 0, 0, 0, 1,
			1, 0, 1, 1, 1]);
			// 2233
			pushCombinations(puzzle);
			
			puzzle = new Matrix(ELEMENT_SIZE, ELEMENT_SIZE, new <int>[
			1, 0, 1, 1, 1,
			1, 0, 0, 0, 1,
			1, 1, 1, 0, 0,
			1, 0, 0, 0, 1,
			1, 1, 0, 1, 1]);
			// 1221
			pushCombinations(puzzle);
			
			puzzle = new Matrix(ELEMENT_SIZE, ELEMENT_SIZE, new <int>[
			1, 1, 1, 0, 0,
			1, 1, 1, 1, 0,
			1, 1, 1, 1, 0,
			0, 1, 1, 1, 0,
			0, 0, 0, 0, 0]);
			pushCombinations(puzzle);
		}
	}
}